from typing import List
from bcat.process.executable import IExecutable
from bcat.process.process import Process

class ExecutableWrapper(object):
    class Wrapper(IExecutable):
        def __init__(self, executable: IExecutable):
            self.__next = executable

        def next(self):
            return self.__next

        def directory(self, value: str) -> IExecutable:
            return self.__next.directory(value)

        def binary(self, value: str) -> IExecutable:
            return self.__next.binary(value)
        def args(self, value: str | List[str]) -> IExecutable:
            return self.__next.args(value)

        def stdout(self, value: bool = False) -> IExecutable:
            return self.__next.stdout(value)
        def stderr(self, value: bool = False) -> IExecutable:
            return self.__next.stderr(value)
        def stdin(self, value: bool = False) -> IExecutable:
            return self.__next.stdin(value)

        def text(self, value: bool = True) -> IExecutable:
            return self.__next.text(value)

        def get_directory(self) -> str:
            return self.__next.get_directory()
        def get_binary(self) -> str:
            return self.__next.get_binary()
        def get_args(self) -> List[str]:
            return self.__next.get_args()
        def get_stdout(self) -> bool:
            return self.__next.get_stdout()
        def get_stderr(self) -> bool:
            return self.__next.get_stderr()
        def get_stdin(self) -> bool:
            return self.__next.get_stdin()
        def get_text(self) -> bool:
            return self.__next.get_text()

        def execute(self) -> Process:
            return self.__next.execute()

        def processes(self) -> List[Process]:
            return self.__next.processes()

    class Stdin(Wrapper):
        def __init__(self, executable: IExecutable):
            super().__init__(executable)
            self.stdin(True)

        def execute(self) -> Process:
            if not self.get_stdin():
                self.stdin(True)
            return self.next().execute()


    class Stdout(Wrapper):
        def __init__(self, executable: IExecutable):
            super().__init__(executable)
            self.stdout(True)

        def execute(self) -> Process:
            if not self.get_stdout():
                self.stdout(True)
            return self.next().execute()

    class Stderr(Wrapper):
        def __init__(self, executable: IExecutable):
            super().__init__(executable)
            self.stderr(True)

        def execute(self) -> Process:
            if not self.get_stderr():
                self.stderr(True)
            return self.next().execute()

    class Text(Wrapper):
        def __init__(self, executable: IExecutable):
            super().__init__(executable)
            self.text(True)

        def execute(self) -> Process:
            if not self.get_stderr():
                self.text(True)
            return self.next().execute()



from bcat.process.executable import Executable
import unittest
class TestWrapper(unittest.TestCase):
    def setUp(self):
        self.__e = Executable().binary("python")
        self.assertFalse(self.__e.get_stdin())
        self.assertFalse(self.__e.get_stdout())
        self.assertFalse(self.__e.get_stderr())

    def tearDown(self):
        self.__e = None

    def test_stdin(self):
        exe = ExecutableWrapper.Stdin(self.__e)
        self.assertTrue(exe.get_stdin())
        process = exe.execute()
        self.assertIsNotNone(process.stdin())

    def test_stdout(self):
        exe = ExecutableWrapper.Stdout(self.__e)
        self.assertTrue(exe.get_stdout())
        process = exe.execute()
        self.assertIsNotNone(process.stdout())
    
    def test_stderr(self):
        exe = ExecutableWrapper.Stderr(self.__e)
        self.assertTrue(exe.get_stderr())
        process = exe.execute()
        self.assertIsNotNone(process.stderr())

    
    def test_text(self):
        exe = ExecutableWrapper.Text(self.__e)
        self.assertTrue(exe.get_text())
        process = exe.execute()
        self.assertTrue(exe.get_text())
